package net.ujacha.sadari.multi.controller;

import java.util.List;
import java.util.UUID;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import net.ujacha.sadari.multi.Character;
import net.ujacha.sadari.multi.Goal;
import net.ujacha.sadari.multi.Note;
import net.ujacha.sadari.multi.NoteFactory;
import net.ujacha.sadari.multi.Paper;
import net.ujacha.sadari.multi.Sadari;
import net.ujacha.sadari.multi.User;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;

@Controller
public class SadariController {

	private static final Logger LOG = Logger.getLogger(SadariController.class);

	private static final String SESSION_USER_KEY = "sadari_user";
	
	@RequestMapping("/")
	public String index(HttpServletRequest request) {
		
		if(getSessionUser(request) != null){
			return "redirect:/note";
		}
		
		return "index";
	}

	@RequestMapping(value="note")
	public String note(@ModelAttribute User user, HttpServletRequest request, ModelMap model) {

		HttpSession session = request.getSession();
		
		try {

			User sessionUser = getSessionUser(request);
			
			if(sessionUser != null){
				
				if(StringUtils.isEmpty(sessionUser.getId())){
					throw new Exception("user id is empty.");
				}
				
			}else{
				if(user == null || StringUtils.isEmpty(user.getName())){
					throw new Exception("user is null or empty name.");
				}
				
				user.setId(UUID.randomUUID().toString());
				user.setAlias(Character.getName(user.getCharacter()));
				session.setAttribute(SESSION_USER_KEY, user);
			}
			
		} catch (Exception e) {

			LOG.warn(e.getMessage());
			
			model.addAttribute("errorMsg", "사용자 정보를 찾을 수 없습니다.");
			return "error";
			
		}
		
		return "note";
	}

	@RequestMapping("note/papers")
	public @ResponseBody
	List<Paper> papers() {
		Note note = NoteFactory.getNote();

		List<Paper> papers = note.listAll();

		return papers;
	}

	@RequestMapping(value = "makePaper", method = RequestMethod.POST)
	public 
	String makePaper(@RequestParam String userId, @RequestParam String paperName, @RequestParam int maxUser, @RequestParam int line, @RequestParam(required=false, defaultValue="false") boolean soloMode, @RequestParam(required=false, defaultValue="false") boolean oneGoal,HttpServletRequest request, ModelMap model) {

		LOG.debug(soloMode + ", " + oneGoal);
		
		User user = getSessionUser(request);

		String id = NoteFactory.getNote().makePaper(user, paperName, maxUser, line, soloMode, oneGoal);
		
		return "redirect:/note/paper/" + id;
	}

	@RequestMapping("note/paper/{paperId}")
	public String enterPaper(@PathVariable String paperId, HttpServletRequest request, ModelMap model) {

		
		User user = getSessionUser(request);
		boolean isLeader = false;

		Paper paper = getPaper(paperId);
		
		if (paper == null) {
			throw new ResourceNotFoundException();
		}

		if(paper.getStatus() < Paper.STATUS_MAKED){

			if(!paper.getUsers().contains(user)){
				if(paper.getMaxUser() <= paper.getUsers().size()){
					model.addAttribute("errorMsg", "인원이 모두 꽉!");
					return "error";
				}
				paper.addUser(user);
			}

			// 리더인지 검사
			if (StringUtils.equals(user.getId(), paper.getLeaderId())) {
				isLeader = true;
			}

			
		}
		model.addAttribute("isLeader", isLeader);
		model.addAttribute("paper", paper);

		return "paper";
	}

	@RequestMapping(value="note/paper/{paperId}/{userId}/{order}", method=RequestMethod.POST)
	public @ResponseBody boolean updateOrder(
			@PathVariable String paperId,
			@PathVariable String userId,
			@PathVariable int order, 
			HttpServletRequest request
			){
		
		boolean b = false;
		
		User user = getSessionUser(request);
		
		if(StringUtils.equals(user.getId(), userId)){
			b = getPaper(paperId).setOrder(user, order);	
		}
		
		return b;
	}
	
	@RequestMapping(value="note/paper/{paperId}/goals", method=RequestMethod.POST)
	public @ResponseBody boolean updateGoal(
			@PathVariable String paperId,
			@RequestParam int order,
			@RequestParam String goalName,
			HttpServletRequest request
			){
		
		boolean b = false;
		
		Goal goal = new Goal(UUID.randomUUID().toString(), goalName);
		b = getPaper(paperId).setGoal(goal , order);	
		
		return b;
	}
	
	@RequestMapping(value="note/paper/{paperId}/goals", method=RequestMethod.GET)
	public @ResponseBody Goal[] getGoals(
			@PathVariable String paperId,						
			HttpServletRequest request
			){
		
		return getPaper(paperId).getGoals();
	}
	
	
	@RequestMapping(value="note/paper/{paperId}/status", method=RequestMethod.GET)
	public @ResponseBody int getStatus(
			@PathVariable String paperId,
			HttpServletRequest request
			){
		
		return getPaper(paperId).getStatus();
	} 
	
	@RequestMapping(value="note/paper/{paperId}/status", method=RequestMethod.POST)
	public @ResponseBody boolean updateStatus(
			@PathVariable String paperId,
			@RequestParam int status,
			HttpServletRequest request
			){
		
		getPaper(paperId).setStatus(status);;
		
		return true; 
	} 
	
	@RequestMapping(value="note/paper/{paperId}/order", method=RequestMethod.GET)
	public @ResponseBody User[] getOrder(
			@PathVariable String paperId,
			HttpServletRequest request
			){
		
		return getPaper(paperId).getOrders();
	} 
	
	@RequestMapping(value="note/paper/{paperId}/model/{line}/{num}", method=RequestMethod.POST)
	public @ResponseBody boolean makeModel(
			@PathVariable String paperId,
			@PathVariable int line,
			@PathVariable int num,
			HttpServletRequest request
			){
		
		int[][] model = Sadari.makeModel(line, num);
		
		getPaper(paperId).setModel(model);
		
		return true;
	} 
	
	@RequestMapping(value="note/paper/{paperId}/model", method=RequestMethod.GET)
	public @ResponseBody int[][] makeModel(
			@PathVariable String paperId,
			HttpServletRequest request
			){
		
		return getPaper(paperId).getModel();
	} 
	
	@RequestMapping("logout")
	public String logout(HttpServletRequest request){
		request.getSession().removeAttribute(SESSION_USER_KEY);
		return "redirect:/";
	}
	
	private User getSessionUser(HttpServletRequest request) {
		HttpSession session = request.getSession();
		User user = (User) session.getAttribute(SESSION_USER_KEY);
		return user;
	}

	private Paper getPaper(String paperId){
		Paper p = NoteFactory.getNote().getPaper(paperId); 
		if(p == null){
			throw new ResourceNotFoundException();
		}
		return p;
	}
	
	@ResponseStatus(value = HttpStatus.NOT_FOUND)
	public class ResourceNotFoundException extends RuntimeException {
		private static final long serialVersionUID = 1194216293671846268L;

	}
	
}
